/*!
\copyright  Copyright (c) 2024 Qualcomm Technologies International, Ltd.
            All Rights Reserved.
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\file       
\ingroup    hci_tap
\brief      This is the interface to HCI TAP Stream that logs the BT HCI Interface
            traffic out off the chip for debugging purpose.

            !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            WARNING: calling hciTapStream_ConfigureUartWithSE functions in the
            code by default is a security risk as the HCI Interface provides
            the LINK Keys.

            Therefore it MUST NEVER be called in the code by DEFAULT in a
            final product.
            !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

            Redirection from HCI TAP Stream to UART through Serial Engine
            Only available for QCC72xx - QCC52xx

            Example:
            ================================
            >>>
            uart_rate = 9600
            serial_engine = 4
            apps.fw.call_vm.HciTapStream_ConnectToUartWithSerialEngine(uart_rate, serial_engine)

@{
*/

#include <hci_tap.h>
#include <hci_tap_private.h>
#include <logging.h>
#include "uart/uart_plat.h"

#if defined(ENABLE_HCI_TAP_STREAM)

HciTapPrivate hciTapPrivateData;

#define CASE_SET_PIN(tx, rx, se) \
  case (se):                     \
    tx = UART_SE##se##_TX_PIN;   \
    rx = UART_SE##se##_RX_PIN;   \
  break;

static bool hciTapStream_ConfigureUartWithSE(vm_uart_rate uart_rate,
                                             uint8 se_number)
{
    uint8 uart_tx_pin = 0;
    uint8 uart_rx_pin = 0;
    uint32 bank = 0;
    uint32 mask = 0;
    switch(se_number)
    {
        /* Assign the appropriate PIOs to be used by UART. */
        CASE_SET_PIN(uart_tx_pin, uart_rx_pin, 0);
        CASE_SET_PIN(uart_tx_pin, uart_rx_pin, 1);
        CASE_SET_PIN(uart_tx_pin, uart_rx_pin, 2);        
        CASE_SET_PIN(uart_tx_pin, uart_rx_pin, 3);
        CASE_SET_PIN(uart_tx_pin, uart_rx_pin, 4);        
        CASE_SET_PIN(uart_tx_pin, uart_rx_pin, 5);
        default:
            return FALSE;
    }
    mask = (1<<uart_tx_pin) | (1<<uart_rx_pin);
    DEBUG_LOG_INFO(HCI_TAPI_STR"Pins TX:%d RX:%d" , uart_tx_pin, uart_rx_pin);
    PioSetMapPins32Bank(bank, mask, 0);
    PioSetFunction(uart_tx_pin, UART_TX);
    PioSetFunction(uart_rx_pin, UART_RX);
    StreamUartConfigureGeneric(uart_rate, VM_UART_STOP_ONE,
                               VM_UART_PARITY_NONE, se_number);
    return TRUE;
}

static bool hciTapStream_ConnectToUartWithSEComplete(uint8 se_number)
{
    Source src = StreamHciTapSource(); /* should be first */
    Sink sink = StreamUartSinkGeneric(se_number);
    bool retVal = hciTapStream_ConnectStream(src, sink);
    if (retVal)
    {
        DEBUG_LOG_INFO(HCI_TAPI_STR"CONNECTED to Uart Stream");
        hciTapPrivateData.state = HCI_TAP_CONNECTED_TO_UART;
    }
    return retVal;
}

bool HciTapStream_ConnectToUartWithSerialEngine(vm_uart_rate uart_rate, uint8 se_number)
{
    if (HCI_TAP_DISCONNECTED != hciTapPrivateData.state)
    {
        DEBUG_LOG_WARN(HCI_TAPW_STR"ALREADY CONNECTED - call testHciTapStream_Disconnect first");
        return FALSE;
    }
    if (se_number > 5)
    {
        DEBUG_LOG_WARN(HCI_TAPW_STR"Unknown Serial Engine Number %d", se_number);
        return FALSE;
    }
    if (hciTapStream_ConfigureUartWithSE(uart_rate, se_number))
    {
        return hciTapStream_ConnectToUartWithSEComplete(se_number);
    }
    return FALSE;
}

bool HciTapStream_ConnectToUart(vm_uart_rate uart_rate,
                                uint8 board_uart_rts,
                                uint8 board_uart_cts,
                                uint8 board_uart_tx,
                                uint8 board_uart_rx)
{
    UNUSED(uart_rate);
    UNUSED(board_uart_rts);
    UNUSED(board_uart_cts);
    UNUSED(board_uart_tx);
    UNUSED(board_uart_rx);
    DEBUG_LOG_WARN(HCI_TAPW_STR"Function HciTapStream_ConnectToUart not \
available for QCC51xx - QCC30xx");
    return FALSE;
}

#endif
